package AneRouge;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;
import javax.swing.JPanel;


public class AneRougePanel extends JPanel implements MouseListener,
		MouseMotionListener {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	final static int delay = 30;

	final static int repaint = 1;

	final static int moving = 2;

	final static int win = 3;

	final static int edge = 80;

	final static int sideX = 512;

	final static int sideY = 600;

	final static int playX = 320;

	final static int playY = 400;

	final static int border = 32;

	final static int buttonX = 5 * edge;

	final static int buttonY = 3 * edge;

	final static int buttonRay = (border / 2) * 3;

	final static int panelX = 4 * edge + 2 * border;

	final static int panelY = edge;

	final static int panelWidth = 2 * (edge - border);

	final static int panelHeight = 2 * border;

	Color couleurFond;

	Image offImage, playImage, boardImage, carrotsImage;

	Graphics offGraphics, playGraphics;

	int blocX[], blocY[], blocWidth[], blocHeight[], blocIX[], blocIY[];;

	int drawMode, movingBloc, hpx, hpy, hx, hy;

	int lastMoving, lastX, lastY, step;

	int stringX, stringY;

	MediaTracker tracker;

	Thread thread;

	boolean inited = false;

	AneRougeBoard board;

	int numBloc;

	AneRougePanel(AneRougeBoard board) {
		this.board = board;
		numBloc = board.numBloc;
		blocIX = new int[numBloc];
		blocIY = new int[numBloc];
		blocX = new int[numBloc];
		blocY = new int[numBloc];

		blocWidth = new int[numBloc];
		blocHeight = new int[numBloc];
		setPreferredSize(new Dimension(sideX, sideY));
	}

	private static Image getImage(String name) {
		InputStream is;
		try {
			is = new BufferedInputStream(new FileInputStream(name));
			return ImageIO.read(is);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	private void init() {
		String codeBase = ".";
	
		offImage = createImage(sideX, sideY);
		offGraphics = offImage.getGraphics();
		offGraphics.setColor(Color.black);
		offGraphics.fillRect(0, 0, sideX, sideY);
		Font font = new Font("Courier", Font.BOLD, 14);
		FontMetrics fm = offGraphics.getFontMetrics(font);
		offGraphics.setFont(font);
		stringX = ((panelWidth - fm.stringWidth("Step XXX")) / 2) + panelX;
		stringY = ((panelHeight + fm.getAscent()) / 2) + panelY;
		playImage = createImage(sideX + playX, sideY);
		playGraphics = playImage.getGraphics();
		playGraphics.setColor(Color.black);
		playGraphics.fillRect(0, 0, sideX + playX, sideY);
		tracker = new MediaTracker(this);
		boardImage = getImage("Board.gif");
		tracker.addImage(boardImage, 0);
		Image setImage = getImage("Set.gif");
		tracker.addImage(setImage, 1);
		carrotsImage = getImage("Carrots.gif");
		tracker.addImage(carrotsImage, 1);
		try {
			tracker.waitForAll();
		} catch (InterruptedException e) {
		}
		;
		playGraphics.drawImage(setImage, sideX, border, this);

	
		resetBoard();
		drawMode = repaint;
	}

	public void mouseClicked(MouseEvent e) {
	}

	public void mouseDragged(MouseEvent e) {
	//	System.out.println(" Drag");

		if (drawMode == moving) {
	//		System.out.println("  .... moving");
			int x = e.getX() - border;
			int y = e.getY() - border;
			int npx = (x / edge) + 1;
			int npy = (y / edge) + 1;
			int dx = npx - hpx - board.blocPX[movingBloc];
			int dy = npy - hpy - board.blocPY[movingBloc];

//			System.out.println("  .... moving " + movingBloc + " " + dx + " "
//					+ dy);

			boolean stop = false;
			for (int dir = 0; dir < 4 && !stop; dir++)
				if ((dx * board.dirX[dir] > 0 || dy * board.dirY[dir] > 0)
						&& board.canMove(movingBloc, dir)) {

			//		System.out.println("  .... moving " + movingBloc + " " + dx
			//				+ " " + dy + " " + dir);
				
					board.moveBloc(movingBloc, dir);
					System.out.println( " hash " + board.longHashCode());
					repaint();
					stop = true;
				}
		}
	}

	public void mouseEntered(MouseEvent e) {
	}

	public void mouseExited(MouseEvent e) {
	}

	public void mouseMoved(MouseEvent e) {
	}

	public void mousePressed(MouseEvent e) {
//		System.out.println(" Press");
		int x = e.getX() - border;
		int y = e.getY() - border;
		if (x >= 0 && x < playX && y >= 0 && y < playY) {
			int px = (x / edge) + 1;
			int py = (y / edge) + 1;
			movingBloc = board.board[px][py];
			System.out.println(" moving block " + movingBloc);

			if (movingBloc != board.empty && drawMode == repaint) {
				hpx = px - board.blocPX[movingBloc];
				hpy = py - board.blocPY[movingBloc];
				hx = x - blocX[movingBloc];
				hy = y - blocY[movingBloc];
				drawMode = moving;
				lastX = board.blocPX[movingBloc];
				lastY = board.blocPY[movingBloc];
			}
		}
		int xx = x - buttonX;
		int yy = y - buttonY;
		int dist2 = xx * xx + yy * yy;
		if (dist2 <= buttonRay * buttonRay) {
			System.out.println(" RESET ");
			drawMode = repaint;
			resetBoard();
			repaint();
		}
	}

	public void mouseReleased(MouseEvent e) {
	//	System.out.println(" Release");

		if (movingBloc < 0)
			return;
		if (lastX != board.blocPX[movingBloc]
				|| lastY != board.blocPY[movingBloc]) {
			if (drawMode == moving && movingBloc == 1) {
				// play(getCodeBase(), "Bray.au");
				if (board.blocPX[movingBloc] == 2
						&& board.blocPY[movingBloc] == 4) {
					drawMode = win;
				}
			}
			if (drawMode == moving && movingBloc != lastMoving) {
				step++;
				lastMoving = movingBloc;
				repaint();
			}
		}
		if (drawMode == moving)
			drawMode = repaint;
	}

	public void paint(Graphics g) {
		if (!inited)
			init();
		inited = true;
		update(g);
		g.drawImage(offImage, 0, 0, this);
	}

	public int getBlockCount() {
		return numBloc;
	}

	public void resetBoard() {
		board.reset();

		for (int n = 0; n < numBloc; n++) {
			blocX[n] = blocIX[n] = edge * (board.blocPX[n] - 1);
			blocY[n] = blocIY[n] = edge * (board.blocPY[n] - 1);

			blocWidth[n] = edge * board.blocDX[n];
			blocHeight[n] = edge * board.blocDY[n];

		}
		step = 0;
		lastMoving = board.empty;
		lastX = -1;
		lastY = -1;
	}

	// public void run() {
	// drawMode = repaint;
	// resetBoard();
	// repaint();
	// while (thread != null) {
	// try {
	// thread.sleep(delay);
	// } catch (InterruptedException e) {
	// }
	// if (drawMode == win) {
	// repaint();
	// }
	// }
	// }
	//
	// public void start() {
	// if (thread == null) {
	// thread = new Thread(this);
	// thread.start();
	// }
	// }
	//
	// public void stop() {
	// if (thread != null) {
	// thread.stop();
	// thread = null;
	// }
	// }

	void updateBoard() {
		for (int i = 0; i < numBloc; i++) {
			int px = board.blocPX[i];
			int py = board.blocPY[i];

			blocX[i] = edge * (px - 1);
			blocY[i] = edge * (py - 1);
		}

	}

	public void update(Graphics g) {

		updateBoard();

		if (drawMode == win && blocY[1] < 400) {
			blocY[1] += 4;
		}
		playGraphics.drawImage(boardImage, 0, 0, this);
		for (int n = 0; n < numBloc; n++) {
			playGraphics.copyArea(blocIX[n] + sideX, blocIY[n]
					+ border, blocWidth[n], blocHeight[n], -sideX + border
					- blocIX[n] + blocX[n], -blocIY[n] + blocY[n]);
		}
		if (drawMode != win) {
			playGraphics.setColor(couleurFond);
			playGraphics.fillRect(0, 464, sideX, 600 - 464);
			playGraphics.drawImage(carrotsImage, border + edge + 10, edge * 5
					+ 2 * border - 10, this);
		}
		offGraphics.drawImage(playImage, 0, 0, this);
		offGraphics.setColor(new Color(10, 200, 130));
		if (drawMode != win)
			offGraphics.drawString("Step " + step, stringX, stringY);
		else
			offGraphics.drawString("You won!", stringX, stringY);
		g.drawImage(offImage, 0, 0, this);
	}
}
